package rootsync

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/cnssl/apps/tools/windows-root-fixer/internal/audit"
	"github.com/cnssl/apps/tools/windows-root-fixer/internal/store"
)

// Syncer 根证书同步器
type Syncer struct {
	logger *audit.Logger
	dryRun bool
}

// NewSyncer 创建新的根证书同步器
func NewSyncer(logger *audit.Logger, dryRun bool) *Syncer {
	return &Syncer{
		logger: logger,
		dryRun: dryRun,
	}
}

// SyncFromWindowsUpdate 从 Windows Update 同步根证书
func (s *Syncer) SyncFromWindowsUpdate() error {
	fmt.Println("从 Windows Update 同步根证书...")

	// 生成临时文件路径
	tempDir := os.TempDir()
	sstFile := filepath.Join(tempDir, "roots.sst")

	// 调用 certutil 生成 roots.sst
	cmd := exec.Command("certutil", "-generateSSTFromWU", sstFile)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("certutil 执行失败: %w\n输出: %s", err, string(output))
	}

	defer os.Remove(sstFile) // 清理临时文件

	// 验证文件是否生成
	if _, err := os.Stat(sstFile); err != nil {
		return fmt.Errorf("roots.sst 文件未生成: %w", err)
	}

	fmt.Printf("已生成 roots.sst: %s\n", sstFile)

	// 导入证书
	return s.importRootsSST(sstFile)
}

// SyncFromURL 从 URL 同步根证书
func (s *Syncer) SyncFromURL(url, expectedSHA256 string) error {
	fmt.Printf("从 URL 下载根证书: %s\n", url)

	// 下载文件
	resp, err := http.Get(url)
	if err != nil {
		return fmt.Errorf("下载失败: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("下载失败: HTTP %d", resp.StatusCode)
	}

	// 生成临时文件
	tempDir := os.TempDir()
	sstFile := filepath.Join(tempDir, "roots.sst")

	f, err := os.Create(sstFile)
	if err != nil {
		return fmt.Errorf("创建临时文件失败: %w", err)
	}
	defer os.Remove(sstFile)

	// 计算 SHA256 并写入文件
	hash := sha256.New()
	writer := io.MultiWriter(f, hash)

	if _, err := io.Copy(writer, resp.Body); err != nil {
		f.Close()
		return fmt.Errorf("保存文件失败: %w", err)
	}
	f.Close()

	// 验证 SHA256
	if expectedSHA256 != "" {
		actualSHA256 := hex.EncodeToString(hash.Sum(nil))
		if actualSHA256 != expectedSHA256 {
			return fmt.Errorf("SHA256 校验失败: 期望 %s, 实际 %s", expectedSHA256, actualSHA256)
		}
		fmt.Println("SHA256 校验通过")
	}

	// 导入证书
	return s.importRootsSST(sstFile)
}

// importRootsSST 导入 roots.sst 文件中的证书
func (s *Syncer) importRootsSST(sstFile string) error {
	if s.dryRun {
		fmt.Printf("[演练] 将从 %s 导入根证书\n", sstFile)
		return nil
	}

	// TODO: 实现最小差异导入逻辑
	// 1. 解析 roots.sst 文件
	// 2. 获取当前系统根存储中的证书列表
	// 3. 比对差异，只导入新增/更新的证书
	// 4. 记录审计日志

	fmt.Println("导入根证书...")

	// 使用 certutil 导入（简化版本）
	cmd := exec.Command("certutil", "-addstore", "-f", "Root", sstFile)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("导入失败: %w\n输出: %s", err, string(output))
	}

	fmt.Println("根证书导入完成")

	// 记录审计日志
	s.logger.Log(audit.AuditEntry{
		Operation:   "import",
		TargetStore: string(store.StoreRoot),
		Success:     true,
	})

	return nil
}
